package com.ruoyi.project.bill.service.impl;


import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.project.bill.domain.*;
import com.ruoyi.project.bill.listerner.BillLisnerInerInterface;
import com.ruoyi.project.bill.service.BillService;
import com.ruoyi.project.bill.service.IBillDefineService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: yp
 * @CreateTime: 2025/7/3
 * @Description: TODO
 * @Version: 1.0
 */
@Service
@Slf4j
public class BillServiceImpl implements BillService {

    @Autowired
    IBillDefineService billDefineService;


    @Autowired
    private ApplicationContext applicationContext;


    @Autowired
    JdbcTemplate jdbcTemplate;

    /**
     * @description:执行动作
     * @author: yp
     * @date: 2025/7/4 11:54
     * @param: [actionCode, bill]
     * @return: void
     **/
    @Override
    public void execAction(String actionCode, Bill bill) {

        String billDefineName = bill.getBillDefine();
        BillDefine billDefine = billDefineService.getBillDefineByDefineName(billDefineName);
        //获取单据所有的动作
        List<BillAction> actionlist =  billDefine.getBillActions();
        BillAction billAction = actionlist.stream().filter(item -> item.getActionCode().equals(actionCode)).findFirst().orElse(null);
        if(billAction==null){
            throw new RuntimeException(actionCode+"该动作单据中未定义!");
        }

       List<BillListener> actionLisitner  =  billAction.getActionLinseners();

        // 执行前置监听器
        for (BillListener listener : actionLisitner) {
            invokeListener(listener.getListenerCode(), bill,"befor");
        }

        // 执行保存操作
        SaveBill(billDefine,bill);

        // 执行后置监听器
        for (BillListener listener : actionLisitner) {

            invokeListener(listener.getListenerCode(), bill,"after");
        }
    }
    /**
     * @description:保存单据
     * @author: yp
     * @date: 2025/7/4 11:54
     * @param: [billDefine, bill]
     * @return: void
     **/
    @Transactional
    public void SaveBill(BillDefine billDefine,Bill bill){

        // 获取主表和子表表名
        String mainTable = billDefine.getMainDataModel();
        String subTable = billDefine.getSubDataModel();
        if(StringUtils.isEmpty(mainTable)){
            throw new RuntimeException("该单据定义关联的主表为空！！");
        }
        BillData billData = bill.getBillData();
        if (bill.getBillData() == null) {
            throw new RuntimeException("主表数据为空，表名：" + mainTable);
        }
        List<BillSubData> subDataList =  bill.getSubBillData("detailList");
        String billId = (String)billData.get("bill_id");
        if(StringUtils.isEmpty(billId)){
            billData.put("bill_id", UUID.fastUUID().toString());
            billData.remove("detailList");
            // 插入主表数据
            insert(mainTable,billData);
        }else {
            Map condition =new HashMap<>();
            condition.put("bill_id",billData.get("bill_id"));
            billData.remove("detailList");
            update(mainTable,billData,condition);

        }

        // 如果存在子表且有数据
        if (StringUtils.isNotEmpty(subTable)) {
            if (subDataList != null && !subDataList.isEmpty()) {
                //先删除子表数据
                Map condition =new HashMap<>();
                condition.put("main_id",billData.get("bill_id"));
                delete(subTable,condition);

                // 插入子表数据
                for (Map<String, Object> subData : subDataList) {

                    // 子表关联主表ID（需要确保主表已保存并获取到主键）
                     subData.put("main_id", (String)billData.get("bill_id"));
                     subData.put("detail_id",UUID.fastUUID().toString());

                    // 插入子表记录
                    insert(subTable,subData);
                }
            }
        }
    }

    /**
     * @description:调用监听器
     * @author: yp
     * @date: 2025/7/4 11:55
     * @param: [listernerCode, bill, type]
     * @return: void
     **/
    public void invokeListener(String listernerCode , Bill bill, String type){

        BillLisnerInerInterface billLisnerIner =  applicationContext.getBean(listernerCode, BillLisnerInerInterface.class);
        //调用监听
        if(type.equals("befor")){
            billLisnerIner.befor(bill);
            System.out.println("执行前置监听: " + listernerCode);

        }else if(type.equals("after")){
            billLisnerIner.after(bill);
            System.out.println("执行后置监听: " + listernerCode);

        }

    }

    /**
     * @description:插入
     * @author: yp
     * @date: 2025/7/4 11:55
     * @param: [tableName, data]
     * @return: int
     **/
    public int insert(String tableName, Map<String, Object> data) {
        StringBuilder sql = new StringBuilder("INSERT INTO ");
        sql.append(tableName).append(" (");

        List<Object> values = new ArrayList<>();
        StringBuilder placeholders = new StringBuilder();

        for (Map.Entry<String, Object> entry : data.entrySet()) {
            if (placeholders.length() > 0) {
                sql.append(", ");
                placeholders.append(", ");
            }
            sql.append(entry.getKey());
            placeholders.append("?");
            values.add(entry.getValue());
        }

        sql.append(") VALUES (").append(placeholders).append(")");
        log.info("单据插入sql:{}",sql);
        return jdbcTemplate.update(sql.toString(), values.toArray());
    }

    /**
     * @description:修改
     * @author: yp
     * @date: 2025/7/4 11:55
     * @param: [tableName, data, condition]
     * @return: int
     **/
    public int update(String tableName, Map<String, Object> data, Map<String, Object> condition) {
        StringBuilder sql = new StringBuilder("UPDATE ");
        sql.append(tableName).append(" SET ");

        List<Object> params = new ArrayList<>();

        // 构建SET部分
        for (Map.Entry<String, Object> entry : data.entrySet()) {
            if (params.size() > 0) {
                sql.append(", ");
            }
            sql.append(entry.getKey()).append(" = ?");
            params.add(entry.getValue());
        }

        // 构建WHERE条件
        if (condition != null && !condition.isEmpty()) {
            sql.append(" WHERE ");
            boolean first = true;
            for (Map.Entry<String, Object> entry : condition.entrySet()) {
                if (!first) {
                    sql.append(" AND ");
                }
                sql.append(entry.getKey()).append(" = ?");
                params.add(entry.getValue());
                first = false;
            }
        }
        log.info("单据修改sql:{}",sql);
        return jdbcTemplate.update(sql.toString(), params.toArray());
    }

    public void delete(String tableName, Map<String, Object> condition){
        String sql = "DELETE FROM " + tableName;
    }
}
